#include "LoginTask.h"
#include "TcpConnection.h"
#include "MessageCodec.h"
#include "protocol.h"
#include "block_log.h"
#include "ConnectPool.h"
#include "ConnectionManager.h"
#include <optional>
#include <thread>
#include <memory>
#include <chrono>

LoginTask::LoginTask(TcpConnection* conn, const std::string& jsonBody)
    : m_conn(conn), m_jsonBody(jsonBody)
{
}

LoginTask::~LoginTask()
{
}

void LoginTask::work(void* arg)
{
    Debug("LoginTask 开始执行，线程 ID: %llu", std::this_thread::get_id());
    
    // 步骤 1: 解析登录请求
    auto loginReqOpt = MessageCodec::loginRequestFromJson(m_jsonBody);
    if (!loginReqOpt) {
        Debug("登录请求 JSON 解析失败");
        
        // 发送错误响应
        LoginResponse errorRes;
        errorRes.success = false;
        errorRes.message = "请求格式错误";
        errorRes.user_id = 0;
        errorRes.token = "";
        
        auto responseData = MessageCodec::encode(errorRes);
        m_conn->sendResponseAsync(responseData);
        return;
    }
    
    LoginRequest req = *loginReqOpt;
    Debug("处理登录请求 - 用户名: %s", req.username.c_str());
    
    // 步骤 2: 从连接池获取数据库连接
    auto connPool = ConnectionPool::getConnectionPool();
    auto dbConn = connPool->getConnection();
    
    if (!dbConn) {
        Debug("获取数据库连接失败");
        
        LoginResponse errorRes;
        errorRes.success = false;
        errorRes.message = "服务器繁忙，请稍后重试";
        errorRes.user_id = 0;
        errorRes.token = "";
        
        auto responseData = MessageCodec::encode(errorRes);
        m_conn->sendResponseAsync(responseData);
        return;
    }
    
    // 步骤 3: 查询数据库验证用户名和密码
    bool success = false;
    uint64_t userId = 0;
    std::string username = "";  // 账号
    std::string nickname = "";  // 昵称
    std::string avatarUrl = ""; // 头像URL
    std::string errorMsg = "账号或密码错误";
    
    try {
        Connection* conn = dbConn->getConnection();
        
        // 使用预编译语句防止 SQL 注入
        std::unique_ptr<PreparedStatement> pstmt(
            conn->prepareStatement(
                "SELECT user_id, username, nickname, avatar_url, password_hash FROM users WHERE username = ? LIMIT 1"
            )
        );
        
        pstmt->setString(1, req.username);
        
        std::unique_ptr<ResultSet> res(pstmt->executeQuery());
        
        if (res->next()) {
            userId = res->getUInt64("user_id");
            username = res->getString("username");  // 从数据库读取账号
            nickname = res->getString("nickname");  // 从数据库读取昵称
            
            // 读取头像URL（可能为NULL）
            if (!res->isNull("avatar_url")) {
                avatarUrl = res->getString("avatar_url");
                Debug("读取到头像URL: [%s]", avatarUrl.c_str());
            } else {
                Debug("用户头像URL为空");
                avatarUrl = "";  // 显式设置为空字符串
            }
            
            std::string dbPassword = res->getString("password_hash");
            
            // 调试：打印密码对比信息
            Debug("密码对比 - 数据库密码: [%s] (长度:%zu), 客户端密码: [%s] (长度:%zu)", 
                  dbPassword.c_str(), dbPassword.length(),
                  req.password.c_str(), req.password.length());
            
            // TODO: 实际项目中应使用 bcrypt 或其他加密算法验证密码
            // 这里为了演示，暂时使用明文比对
            if (dbPassword == req.password) {
                success = true;
                
                // 更新最后登录时间
                std::unique_ptr<PreparedStatement> updateStmt(
                    conn->prepareStatement(
                        "UPDATE users SET last_login_at = NOW(), status = 1 WHERE user_id = ?"
                    )
                );
                updateStmt->setUInt64(1, userId);
                updateStmt->executeUpdate();
                
                Debug("用户 %s (ID: %llu) 登录成功", req.username.c_str(), userId);
            } else {
                errorMsg = "密码错误";
                Debug("用户 %s 密码错误", req.username.c_str());
            }
        } else {
            errorMsg = "用户不存在";
            Debug("用户 %s 不存在", req.username.c_str());
        }
        
    } catch (const SQLException& e) {
        Debug("数据库查询异常: %s (错误码: %d)", e.what(), e.getErrorCode());
        errorMsg = "服务器内部错误";
        success = false;
    }
    
    // 步骤 4: 登录成功后，将用户ID保存到连接对象中（长连接不需要 token）
    if (success) {
        m_conn->setUserId(userId);
        // 注册到全局连接管理器
        ConnectionManager::getInstance()->registerConnection(userId, m_conn);
        Debug("用户 %s (ID: %lu) 登录成功，已设置到连接并注册到管理器", req.username.c_str(), userId);
        
        // 步骤 4.1: 通知该用户的所有好友：该用户已上线
        try {
            auto dbConn = connPool->getConnection();
            if (dbConn) {
                sql::Connection* conn = dbConn->getConnection();
                
                // 查询该用户的所有好友
                std::unique_ptr<sql::PreparedStatement> queryStmt(
                    conn->prepareStatement(
                        "SELECT friend_id FROM friendships WHERE user_id = ?"
                    )
                );
                queryStmt->setUInt64(1, userId);
                std::unique_ptr<sql::ResultSet> friendRes(queryStmt->executeQuery());
                
                std::vector<uint64_t> friendIds;
                while (friendRes->next()) {
                    uint64_t friendId = friendRes->getUInt64("friend_id");
                    friendIds.push_back(friendId);
                }
                
                Debug("用户 %lu 上线，通知 %zu 个好友", userId, friendIds.size());
                
                // 构造上线通知
                FriendStatusNotify notify;
                notify.user_id = userId;
                notify.status = 1;  // 在线
                notify.timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
                    std::chrono::system_clock::now().time_since_epoch()
                ).count();
                
                auto notifyData = MessageCodec::encode(notify);
                
                // 推送给在线的好友
                int notifyCount = 0;
                for (uint64_t friendId : friendIds) {
                    TcpConnection* friendConn = ConnectionManager::getInstance()->getConnection(friendId);
                    if (friendConn) {
                        friendConn->sendResponseAsync(notifyData);
                        notifyCount++;
                        Debug("已通知好友 %lu：用户 %lu 已上线", friendId, userId);
                    }
                }
                
                Debug("成功通知 %d 个在线好友用户上线", notifyCount);
            }
        } catch (const sql::SQLException& e) {
            Debug("推送好友上线通知失败: %s", e.what());
            // 不影响登录流程，继续执行
        }
    }
    
    // 步骤 5: 构造登录响应
    LoginResponse response;
    response.success = success;
    response.message = success ? "登录成功" : errorMsg;
    response.username = success ? username : "";  // 返回账号
    response.nickname = success ? nickname : "";  // 返回昵称
    response.avatar_url = success ? avatarUrl : "";  // 返回头像URL
    response.user_id = success ? userId : 0;
    response.token = "";  // 长连接不需要 token
    
    Debug("登录%s - 账号: %s, user_id: %lu", 
          success ? "成功" : "失败", 
          req.username.c_str(), 
          response.user_id);
    Debug("响应数据 - username: [%s], nickname: [%s], avatar_url: [%s]", 
          response.username.c_str(), 
          response.nickname.c_str(),
          response.avatar_url.c_str());
    
    // 步骤 5: 编码响应并异步发送（线程安全）
    auto responseData = MessageCodec::encode(response);
    
    // 打印完整的JSON（用于调试）
    std::string jsonStr = MessageCodec::toJson(response);
    Debug("发送登录响应JSON: %s", jsonStr.c_str());
    
    m_conn->sendResponseAsync(responseData);
    
    Debug("LoginTask 执行完成");
}
